#include <iostream>
#include <unistd.h>
#include <pthread.h>
#include <vector>
#include <list>
#include <queue>
const int dcap = 4;
template <class T>
class bqueue:public std::list<T>
{
private:
    int _cap;
    pthread_mutex_t _mtx;
    pthread_cond_t _full_cond;
    pthread_cond_t _empty_cond;
    int _get_times=0;
    int _put_times=0;
    int _p_sleep_cnt=0;
    int _c_sleep_cnt=0;
public:
    // base func
    bqueue(int cap = dcap);
    ~bqueue();
    // feature
    T put(T el);
    T get();
    //iterator...
};

template <class T>
bqueue<T>::bqueue(int cap)
    : _cap(cap)
{
    pthread_mutex_init(&_mtx, nullptr);
    pthread_cond_init(&_full_cond, nullptr);
    pthread_cond_init(&_empty_cond, nullptr);
}

template <class T>
bqueue<T>::~bqueue()
{
    pthread_mutex_destroy(&_mtx);
    pthread_cond_destroy(&_full_cond);
    pthread_cond_destroy(&_empty_cond);
}

template <class T>
inline T bqueue<T>::put(T el)
{
    usleep(1000);
    pthread_mutex_lock(&_mtx);
    while (this->size() >= _cap)
    {
        _p_sleep_cnt++;
        pthread_cond_wait(&_empty_cond, &_mtx);
        _p_sleep_cnt--;
    }
    this->emplace_back(el);
    printf("%d.put\n",++_put_times);
    // if (this->size() == _cap)
    // if(this->size())
    // sleep(1);
    // printf("有%d个消费者在休眠\n",_c_sleep_cnt);
    if(_c_sleep_cnt && this->size() == _cap)
        pthread_cond_signal(&_full_cond);
    pthread_mutex_unlock(&_mtx);
    return el;
}
template <class T>
inline T bqueue<T>::get()
{
    // printf("是消费者在等待\n");
    usleep(1000);
    pthread_mutex_lock(&_mtx);
    while (this->size() == 0)
    {
        // printf("是消费者在等待\n");
        _c_sleep_cnt++;
        pthread_cond_wait(&_full_cond,&_mtx);
        _c_sleep_cnt--;
    }
    T ret = this->front();this->pop_front();
    std::cout<<++_get_times<<"get\n";
    // sleep(1);
    // printf("有%d个生产在休眠\n",_p_sleep_cnt);
    // if (this->size() == 0)
    if(_p_sleep_cnt && this->size() == 0)
        pthread_cond_signal(&_empty_cond);
    pthread_mutex_unlock(&_mtx);
    return ret;
}
